import psutil
import subprocess
from src.model.cpu_info import CpuInfo
from loguru import logger

from pySMART import DeviceList
from src.model.disk_info import DiskInfo
from src.model.memory_info import MemoryInfo
from src.multi_platform.hardware_info_interface import HardwareInfoInterface


class HardwareInfoLinuxImpl(HardwareInfoInterface):

    def get_cpu_info(self) -> CpuInfo:
        info = CpuInfo()
        info.physical_core_count = psutil.cpu_count(logical=False)
        info.logic_core_count = psutil.cpu_count(logical=True)
        cpu_freq = psutil.cpu_freq()
        info.min_frequency = cpu_freq.min
        info.max_frequency = cpu_freq.max
        info.current_frequency = cpu_freq.current
        with open('/proc/cpuinfo') as f:
            for line in f:
                if 'model name' in line:
                    info.model = line.strip().split(': ')[1]
                    break
        try:
            sensors_output = subprocess.check_output(['sensors']).decode('utf-8')
            for line in sensors_output.split('\n'):
                if 'Package id 0' in line:
                    info.temperature = line.split(':')[1].strip()
        except subprocess.CalledProcessError:
            logger.warning("Failed to retrieve CPU temperature.")
        return info

    def get_memory_info(self) -> MemoryInfo:
        info = MemoryInfo()
        mem_info = psutil.virtual_memory()
        info.total = mem_info.total / (1024 ** 3)
        info.available = mem_info.available / (1024 ** 3)
        info.used = mem_info.used / (1024 ** 3)
        info.usage = mem_info.percent
        return info

    def get_disk_infos(self) -> list[DiskInfo]:
        infos = []

        result = subprocess.run(['df', '-B1'], stdout=subprocess.PIPE, text=True)
        # 将输出按行分割
        lines = result.stdout.splitlines()
        # 存储分区信息的列表
        partitions = []
        # 忽略第一行（标题行）
        for line in lines[1:]:
            parts = line.split()
            if len(parts) >= 6:
                partition_info = {
                    'filesystem': parts[0],  # 文件系统
                    'size': parts[1],  # 总大小
                    'used': parts[2],  # 已使用大小
                    'available': parts[3],  # 可用大小
                    'usage': parts[4],  # 使用率
                    'mounted_on': parts[5]  # 挂载点
                }
                partitions.append(partition_info)
        disks = DeviceList()
        for disk in disks:
            info = DiskInfo()
            infos.append(info)
            info.model = disk.model
            info.temperature = disk.temperature
            info.name = disk.name
            info.total = disk.size
            info.serial = disk.serial
            for partition in partitions:
                if partition['filesystem'].startswith(disk.dev_reference):
                    info.used += int(partition['used'])
                    info.available += int(partition['available'])
                    info.partition_count += 1
            info.usage = info.used * 100 / info.total

        return infos
